`include "define.sv"

module top (
    // AXI全局信号
    input  wire          ACLK,
    input  wire          ARESETN,

    // AXI写地址通道（由内部axi_master驱动，作为top模块的输出）
    output wire [31:0]   m_AWADDR,
    output wire [7:0]    m_AWLEN,
    output wire [2:0]    m_AWSIZE,
    output wire [1:0]    m_AWBURST,
    output wire          m_AWVALID,
    input  wire          s_AWREADY, // 来自外部AXI从设备的就绪信号（作为top模块的输入）

    // AXI写数据通道（由内部axi_master驱动，作为top模块的输出）
    output wire [31:0]   m_WDATA,
    output wire [3:0]    m_WSTRB,
    output wire          m_WLAST,
    output wire          m_WVALID,
    input  wire          s_WREADY,  // 来自外部AXI从设备的就绪信号（作为top模块的输入）

    // AXI写响应通道（由外部AXI从设备驱动，作为top模块的输入）
    input  wire [1:0]    s_BRESP,
    input  wire          s_BVALID,
    output wire          m_BREADY,  // 由内部axi_master驱动的就绪信号（作为top模块的输出）

    // APB配置接口
    input  wire          PCLK,
    input  wire          PRESETn,
    input  wire [31:0]   PADDR,
    input  wire          PWRITE,
    input  wire [31:0]   PWDATA,
    input  wire          PENABLE,
    input  wire          PSEL,
    output wire [31:0]   PRDATA,
    output wire          PREADY,
    output wire          PSLVERR,

    // 新增输出端口 (由内部模块驱动)
    output wire [31:0]   ram_dout,
    output wire          burst_done,
    output wire [1:0]    matrix_type,
    output wire [1:0]    data_type,
    output wire          mix_precision,
    output wire          axi_start,
    output wire [9:0]    axi_write_addr,
    output wire [31:0]   axi_write_data,
    output wire          axi_write_valid,
    output wire          axi_done
);

//---------------- 内部信号声明 ------------------
wire [31:0] c_out_muxed;

// 声明非压缩数组类型信号
wire [31:0] a_din_array [0:31]; // 32元素的32位非压缩数组
wire [31:0] b_din_array [0:31];
wire [31:0] c_din_array [0:31][0:31];

// 控制信号（非压缩数组）
wire a_wr_en [0:31];
wire b_wr_en [0:31];
wire c_wr_en [0:31][0:31];

// 用于连接内部AXI主设备和从设备的内部AXI信号
wire [31:0] internal_awaddr;
wire [7:0]  internal_awlen;
wire [2:0]  internal_awsize;
wire [1:0]  internal_awburst;
wire        internal_awvalid;
wire        internal_awready;

wire [31:0] internal_wdata;
wire [3:0]  internal_wstrb;
wire        internal_wlast;
wire        internal_wvalid;
wire        internal_wready;

wire [1:0]  internal_bresp;
wire        internal_bvalid;
wire        internal_bready;

// 复制ram_dout到各个输入通道
genvar i, j;
generate
    for (i = 0; i < 32; i++) begin : gen_input_arrays
        assign a_din_array[i] = ram_dout;
        assign b_din_array[i] = ram_dout;

        for (j = 0; j < 32; j++) begin : gen_c_array
            assign c_din_array[i][j] = ram_dout;
        end
    end
endgenerate

// 生成写使能信号
generate
    for (i = 0; i < 32; i++) begin : gen_wr_en
        assign a_wr_en[i] = burst_done;
        assign b_wr_en[i] = burst_done;

        for (j = 0; j < 32; j++) begin : gen_c_wr_en
            assign c_wr_en[i][j] = burst_done;
        end
    end
endgenerate

//---------------- AXI Adapter实例化 ------------------
// 该模块将内部处理结果c_out_muxed转换为AXI写入数据
axi_adapter u_axi_adapter (
    .clk(ACLK),
    .reset(!ARESETN),
    .c_out_muxed(c_out_muxed),
    .axi_write_data(axi_write_data),
    .axi_write_valid(axi_write_valid),
    .axi_write_addr(axi_write_addr),
    .axi_start(axi_start),
    .axi_done(axi_done)
);

//---------------- AXI Slave实例化 ------------------
// 该模块模拟一个AXI从设备，接收来自内部AXI主设备的请求，并驱动响应信号。
// 它可以将接收到的AXI数据传递给RAM控制器。
axi_slave u_axi (
    .ACLK(ACLK),
    .ARESETN(ARESETN),
    .AWADDR(internal_awaddr),
    .AWLEN(internal_awlen),
    .AWSIZE(internal_awsize),
    .AWBURST(internal_awburst),
    .AWVALID(internal_awvalid),
    .AWREADY(internal_awready), // 由此从设备驱动
    .WDATA(internal_wdata),
    .WSTRB(internal_wstrb),
    .WLAST(internal_wlast),
    .WVALID(internal_wvalid),
    .WREADY(internal_wready),  // 由此从设备驱动
    .BRESP(internal_bresp),    // 由此从设备驱动
    .BVALID(internal_bvalid),  // 由此从设备驱动
    .BREADY(internal_bready)
);

//---------------- APB Slave实例化 ------------------
// 该模块处理APB总线上的配置请求，并输出矩阵类型、数据类型等控制参数。
apb_slave u_apb_slave (
    .PCLK(PCLK),
    .PRESETn(PRESETn),
    .PADDR(PADDR),
    .PWRITE(PWRITE),
    .PWDATA(PWDATA),
    .PENABLE(PENABLE),
    .PSEL(PSEL),
    .PRDATA(PRDATA),
    .PREADY(PREADY),
    .PSLVERR(PSLVERR),
    .matrix_type(matrix_type),
    .data_type(data_type),
    .mix_precision(mix_precision)
);

//---------------- RAM控制器实例化 ------------------
// 该模块根据AXI总线上的写操作控制RAM，并将RAM读取的数据通过ram_dout输出。
memory_controller #(
    .DATA_WIDTH(32),
    .ADDR_WIDTH(10)
) u_ram_ctrl (
    .clk(ACLK),
    .rst_n(ARESETN),
    .matrix_type(matrix_type),
    .data_type(data_type),
    .we(internal_wvalid & internal_wready), // 使用内部AXI数据有效/就绪信号作为写使能
    .addr(internal_awaddr[9:0]),            // 使用内部AXI地址作为RAM地址
    .din(internal_wdata),                  // 使用内部AXI写数据作为RAM输入数据
    .burst_len(internal_awlen),            // 使用内部AXI突发长度
    .dout(ram_dout),
    .burst_done(burst_done)
);

//---------------- 脉动阵列系统实例化 ------------------
// 核心计算模块，执行矩阵运算，并将结果输出到c_out_muxed。
systolic_system u_systolic_system (
    .clk(ACLK),
    .reset(!ARESETN),
    .a_din(a_din_array),
    .a_wr_en(a_wr_en),
    .b_din(b_din_array),
    .b_wr_en(b_wr_en),
    .c_din(c_din_array),
    .c_wr_en(c_wr_en),
    .matrix_type(matrix_type),
    .data_type(data_type),
    .mix_precision(mix_precision),
    .c_out_muxed(c_out_muxed)
);

//---------------- AXI Master实例化（唯一驱动AXI写地址和数据）------------------
// 该模块作为AXI主设备，根据axi_adapter的请求发起AXI写操作。
axi_master u_axi_master (
    .clk(ACLK),
    .reset_n(ARESETN),
    // AXI写地址通道（驱动内部信号）
    .awaddr(internal_awaddr),
    .awlen(internal_awlen),
    .awsize(internal_awsize),
    .awburst(internal_awburst),
    .awvalid(internal_awvalid),
    .awready(internal_awready), // 接收来自从设备的就绪信号
    // AXI写数据通道（驱动内部信号）
    .wdata(internal_wdata),
    .wstrb(internal_wstrb),
    .wlast(internal_wlast),
    .wvalid(internal_wvalid),
    .wready(internal_wready),   // 接收来自从设备的就绪信号
    // AXI写响应通道（接收来自从设备）
    .bresp(internal_bresp),
    .bvalid(internal_bvalid),
    .bready(internal_bready),   // 驱动就绪信号给从设备
    // 用户控制接口 (与axi_adapter协同工作)
    .start(axi_start),
    .read_write(1'b0), // 假设此主设备仅执行写操作
    .addr({22'b0, axi_write_addr}), // 将axi_write_addr扩展到32位地址
    .burst_len(8'd1),
    .burst_size(3'b10),
    .burst_type(2'b01),
    .write_data(axi_write_data),
    .done(axi_done)
);

// 将内部AXI信号连接到顶层模块的输出/输入端口
// AXI写地址通道的输出连接
assign m_AWADDR    = internal_awaddr;
assign m_AWLEN     = internal_awlen;
assign m_AWSIZE    = internal_awsize;
assign m_AWBURST   = internal_awburst;
assign m_AWVALID   = internal_awvalid;
assign internal_awready   = s_AWREADY; // 将外部从设备的就绪信号连接到内部信号

// AXI写数据通道的输出连接
assign m_WDATA     = internal_wdata;
assign m_WSTRB     = internal_wstrb;
assign m_WLAST     = internal_wlast;
assign m_WVALID    = internal_wvalid;
assign internal_wready    = s_WREADY;  // 将外部从设备的就绪信号连接到内部信号

// AXI写响应通道的输入/输出连接
assign s_BRESP     = internal_bresp;
assign s_BVALID    = internal_bvalid;
assign internal_bready    = m_BREADY;  // 将内部主设备的就绪信号连接到外部输出

endmodule